#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import socket
from dotenv import dotenv_values
import os
import shutil
import subprocess

PORT_START = 12101
PORT_END = 12113
DOCKER_ENV_FILE_NAME = "docker.env"
SKY_WALKING_AGENT = "apache-skywalking-java-agent-8.9.0.tgz"


class DockerStartupException(Exception):
    def __init__(self, message):
        self.message = message

    def __str__(self):
        return self.message


def print_blank():
    for i in range(0, 3):
        print("")


def is_port_in_use(port):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)  # 设置连接超时时间
        result = sock.connect_ex(("localhost", port))
        if result == 0:
            return False
        else:
            return True
    except socket.error as e:
        print(f"Error: {e}")
    finally:
        sock.close()


def check_ports():
    print("step 01: 检查端口号...")
    for port in range(PORT_START, PORT_END + 1):
        if not is_port_in_use(port):
            raise DockerStartupException(f"端口号:【{port}】被占用")
        else:
            print(f"端口号:【{port}】可用")
    print("=======> 检查端口号结束")


def get_base_ip_prefix():
    env = dotenv_values(DOCKER_ENV_FILE_NAME)
    ip_prefix = env["THRESH_DEV_NETWORK_IP_PREFIX"]
    if not ip_prefix.strip():
        raise DockerStartupException("未设置 docker 网关前缀")
    return ip_prefix


def get_base_dir():
    env = dotenv_values(DOCKER_ENV_FILE_NAME)
    dir = env["THRESH_DEV_BASE_DIR"]
    if not dir.strip():
        raise DockerStartupException("未设置 docker 跟目录")
    return dir


def assert_base_dir(base_dir):
    if os.path.exists(base_dir):
        raise DockerStartupException(f"docker 跟目录【{base_dir}】已存在,请备份相关文件后删除此目录或重新指定跟目录")


def copy_config_files(base_dir):
    print("step 03:复制配置文件...")
    print("复制 es 配置文件")
    shutil.copytree("./es", f"{base_dir}/es")
    print("复制 kibana 配置文件")
    shutil.copytree("./kibana", f"{base_dir}/kibana")
    print("复制 logstash 配置文件")
    shutil.copytree("./logstash", f"{base_dir}/logstash")
    print("复制 mysql 配置文件")
    shutil.copytree("./mysql", f"{base_dir}/mysql")
    print("复制 nginx 配置文件")
    shutil.copytree("./nginx", f"{base_dir}/nginx")

    print("删除 .keep 文件")
    subprocess.call(f"find {base_dir} -type f -name '.keep' -delete", shell=True)

    print("复制并解压 skywalking agent")
    shutil.copy2(f"../{SKY_WALKING_AGENT}", f"{base_dir}/{SKY_WALKING_AGENT}")
    subprocess.call(f"cd {base_dir} && tar xf {SKY_WALKING_AGENT}", shell=True)

    print("设置相关目录权限")
    subprocess.call(f"chmod -R 777 {base_dir}/es/data", shell=True)
    subprocess.call(f"chmod -R 777 {base_dir}/es/logs", shell=True)
    subprocess.call(f"chmod -R 777 {base_dir}/logstash/data", shell=True)
    subprocess.call(f"chmod -R 777 {base_dir}/mysql/standalone/log", shell=True)

    pass


def check_network():
    print("step 04:检查网关是否可用")
    ip_prefix = get_base_ip_prefix()
    print(f"网关前缀:【{ip_prefix}】")
    result = subprocess.run(
        f"docker network ls | grep '{ip_prefix}.*.*'",
        shell=True,
        capture_output=True,
        text=True,
    )
    if result.stdout.strip():
        raise DockerStartupException(f"有网关占用了【{ip_prefix}】,请删除该网关或修改网关前缀")


def start_server():
    print("step 05:根据提示操作")
    print("在 dox/docker_local 目录下执行一下命令")
    print("docker-compose --env-file=docker.env up -d")
    print(
        'docker exec -i thresh-dev-mysql mysql -uroot -proot -e "create database thresh character set utf8mb4 collate utf8mb4_general_ci;"'
    )
    print("docker exec -i thresh-dev-mysql mysql -uroot -proot thresh < thresh.sql")


if __name__ == "__main__":
    print("开始设置本地开发环境")
    try:
        check_ports()
        print_blank()
        base_dir = get_base_dir()
        assert_base_dir(base_dir)
        print("step 02: 检查跟目录...")
        print("docker 跟目录:{}".format(base_dir))
        print_blank()
        copy_config_files(base_dir)
        print_blank()
        check_network()
        print_blank()
        start_server()
        print_blank()
        print("本地开发环境设置完毕!!!")
    except DockerStartupException as e:
        print("设置环境出错")
        print(e)
